package autoupdate.test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CRC32;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

import common.test.Module;

public class InputStreamWorker extends SwingWorker<Void, DLoadProgress>{

	
	private JFrame jFrame;
	private JProgressBar aJProgressBar;
	private JLabel jLabel1;
	private JLabel jLabel2;
	private Module module;
	

	public InputStreamWorker(JFrame jFrame, JProgressBar progressBar, JLabel label1, JLabel label2, Module module){
		super();
		this.aJProgressBar = progressBar;
		this.jLabel1 = label1;
		this.jLabel2 = label2;
		this.jFrame = jFrame;
		this.module = module;
	}

	@Override
	protected Void doInBackground(){
		
		try{
			readFile();
		}catch(NoSuchAlgorithmException e){
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch(IOException e){
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
		return null;
	}

	@Override
	protected void process(List<DLoadProgress> progressList){
		DLoadProgress dlp = progressList.get(progressList.size() - 1);
		aJProgressBar.setValue(dlp.getProgress());
		int listCount = progressList.size();
		double currentSpeed = 0;
		for(int i = 0; i < listCount; i++){
			DLoadProgress dLoadProgress = progressList.get(i);
			currentSpeed += dLoadProgress.getCurrentSpeed();
		}
		currentSpeed /= listCount;
		jLabel1.setText(currentSpeed + "KB/s");
		jLabel2.setText(dlp.getAverageSpeed() + "KB/s");
	}
	
	private void readFile() throws IOException, NoSuchAlgorithmException{
//		start timing
		long startMillis = System.currentTimeMillis();
		long timeAdler32 = 0L;
		long timeCRC32 = 0L;
		long timeMD5 = 0L;
		long timeSHA1 = 0L;
		long timeWrite = 0L;
		long timeCalc = 0L;
		long timeRead = 0L;
		long start = 0L;
		long startDload = 0L;
		long currentDuration;
		long sDur = startMillis;
		long eDur;
		long dur;
		int startBytes = 0;
		
		
		String fileName = module.getUpdateLocation() + module.getModuleFilename();
		URL url = new URL(fileName);
		System.out.println(fileName);
		
//		String fileName = "usr.zip";
//		URL url = new URL("http://localhost/content/" + fileName);
		
//		String fileName = "test.abc";
//		URL url = new URL("http://livelink.thrivent.com/Livelink/llisapi.dll?func=ll&objId=31318351&objAction=download&viewType=1");
		
		
		URLConnection connection = url.openConnection();
		int fileSize = connection.getContentLength();
		//int fileSize = 1000000;
		System.out.println(fileSize);
		
		InputStream inStream = url.openStream();
		DataInputStream dis = new DataInputStream(new BufferedInputStream(inStream));
		DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(module.getModuleFilename() + ".upd")));
		
		DLoadProgress dlp = new DLoadProgress();
		
		MessageDigest checksumMD5 = MessageDigest.getInstance("MD5");
		MessageDigest checksumSHA1 = MessageDigest.getInstance("SHA-1");
		Adler32 checksumAdler32 = new Adler32();
		CRC32 checksumCRC32 = new CRC32();
		int bytesRead = 0;
		int totalBytes = 0;
		byte data[] = new byte[1024];
		start = System.currentTimeMillis();
		startDload = start;
		while((bytesRead = dis.read(data)) > -1){
			totalBytes += bytesRead;
			timeRead += (System.currentTimeMillis() - start);
			
			start = System.currentTimeMillis();
			dos.write(data,0,bytesRead);
			timeWrite += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumAdler32.update(data, 0, bytesRead);
			timeAdler32 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumCRC32.update(data, 0, bytesRead);
			timeCRC32 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumMD5.update(data, 0, bytesRead);
			timeMD5 += (System.currentTimeMillis() - start);
			start = System.currentTimeMillis();
			checksumSHA1.update(data, 0, bytesRead);
			timeSHA1 += (System.currentTimeMillis() - start);
			
			start = System.currentTimeMillis();
			int progress = Math.round((100f * totalBytes) / fileSize);
			
			currentDuration = System.currentTimeMillis() - startMillis;
			double averageSpeed = 1 * totalBytes / currentDuration;
			
			eDur = System.currentTimeMillis();
			dur = eDur - sDur;
			double currentSpeed = 1 * (totalBytes - startBytes) / dur;
			if(dur >= 5000d){
				sDur += (dur / 2);
				startBytes += ((totalBytes - startBytes) / 2);
			}	
			dlp.setCurrentSpeed(currentSpeed);
			dlp.setAverageSpeed(averageSpeed);
			dlp.setProgress(progress);
			//System.out.println(totalBytes);
			//System.out.println(progress);
			//if(bytesRead == 0)
				//System.out.println(bytesRead);
			publish(dlp);
			timeCalc += (System.currentTimeMillis() - start);
			
			start = System.currentTimeMillis();
		}
		
		start = System.currentTimeMillis();
		String resultMD5 = "";
		data = checksumMD5.digest();
		 for (int i=0; i < data.length; i++) {
			 resultMD5 +=
			   Integer.toString( ( data[i] & 0xff ) + 0x100, 16).substring( 1 );
		  }
		 timeMD5 += (System.currentTimeMillis() - start);
		 
		 start = System.currentTimeMillis();
		 String resultSHA1 = "";
		 data = checksumSHA1.digest();
		 for (int i=0; i < data.length; i++) {
			 resultSHA1 +=
		      Integer.toString( ( data[i] & 0xff ) + 0x100, 16).substring( 1 );
		  }
		 timeSHA1 += (System.currentTimeMillis() - start);
		 
		System.out.println("Bytes:\t\t" + totalBytes);
		System.out.println("Adler32:\t" + timeAdler32 + "ms\t" + checksumAdler32.getValue());
		System.out.println("CRC32:\t\t" + timeCRC32 + "ms\t" + checksumCRC32.getValue());		
		System.out.println("MD5:\t\t" + timeMD5 + "ms\t" + resultMD5);		
		System.out.println("SHA1:\t\t" + timeSHA1 + "ms\t" + resultSHA1);
		System.out.println("Read:\t\t" + timeRead + "ms\t");
		System.out.println("Write:\t\t" + timeWrite + "ms\t");
		System.out.println("Calc:\t\t" + timeCalc + "ms\t");
		long waste = (System.currentTimeMillis() - startDload) - (timeAdler32 + timeCRC32 + timeMD5 + timeSHA1 + timeRead + timeWrite + timeCalc);
		System.out.println("Waste:\t\t" + waste + "ms\t");
		
		dos.flush();
		dos.close();
		dis.close();
		
//		End timing
		System.out.println((System.currentTimeMillis() - startMillis) + "ms");
		
	}
	
	@Override
	protected void done(){
		jFrame.setVisible(false);
		jFrame.dispose();
		jFrame = null;
		
		//AutoUpdater.patch(module.getModuleFilename() + AutoUpdateConstants.UPDATE_FILE_SUFFIX);
		System.out.println("done");
	}

}
